from django.conf import settings
from rest_framework import serializers
from rest_framework import HTTP_HEADER_ENCODING
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.settings import api_settings

from mysqldb.models import (
    AllinpayUserList,
    AllinpayPlaceList,
    AllinpayStaffList,
    AllinpayPlacestaffList,
    AllinpayPlacestaffExtend,
    GamePlacetokenList,
    GamoPlacetokenList,
)

from datetime import datetime, date, timedelta


def JwtResUserID(token, user=None, request=None):
    print("........")
    data = {
        "token": token,
        "username": user.name,
        "user_id": user.id,
    }
    return data


class MyJWTAuthentication(JWTAuthentication):
    """自定义身份验证- 后台"""

    def get_raw_header(self, header):
        parts = header.split()
        if len(parts) == 0:
            return None
        return parts[0]

    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        # 验证登录类型
        raw_header = self.get_raw_header(header)
        if raw_header is None or raw_header != "Bearer".encode():
            return None

        print("管理员认证")

        validated_token = self.get_validated_token(raw_token)
        return self.get_user(validated_token), validated_token

    def get_user(self, validated_token):
        """
        Attempts to find and return a user using the given validated token.
        """
        self.user_model = AllinpayUserList
        try:
            user_id = validated_token[api_settings.USER_ID_CLAIM]
        except BaseException as err:
            raise serializers.ValidationError(["令牌不包含可识别的用户标识"])

        try:
            user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
        except BaseException as err:
            raise serializers.ValidationError(["用户不存在"])

        if user.is_super:
            return user  # 超级管理员
        if not user.status:
            raise serializers.ValidationError(["用户已锁定"])  # 被禁用
        if not user.is_active:
            raise serializers.ValidationError(["用户未激活"])  # 未激活
        if not user.is_authenticated:
            raise serializers.ValidationError(["用户已禁用"])  # 禁止登录后台

        print("验证管理员")
        return user


class BoxJWTAuthentication(JWTAuthentication):
    """场所端盒子服务器验证"""

    def get_raw_header(self, header):
        parts = header.split()
        if len(parts) == 0:
            return None
        return parts[0]

    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        # 验证登录类型
        raw_header = self.get_raw_header(header)
        if raw_header is None or raw_header != "Pearer".encode():
            return None

        print("盒子认证")

        validated_token = self.get_validated_token(raw_token)
        return self.get_user(validated_token), validated_token

    def get_user(self, validated_token):
        """
        Attempts to find and return a user using the given validated token.
        """
        self.user_model = AllinpayPlaceList
        try:
            user_id = validated_token[api_settings.USER_ID_CLAIM]
        except BaseException as err:
            raise serializers.ValidationError(["令牌不包含可识别的用户标识"])

        try:
            user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
        except BaseException as err:
            raise serializers.ValidationError(["场所不存在"])

        if not user.status:
            raise serializers.ValidationError(["场所已锁定"])  # 被禁用

        print("验证场所")
        return user


class WeChatJWTAuthentication(JWTAuthentication):
    """微信端服务器验证"""

    def get_placer(self, request):
        try:
            header = request.META.get("HTTP_HTTPPLACEID")
            header = AllinpayPlaceList.objects.get(id=header)
            return header
        except BaseException as err:
            return None

    def get_staff(self, request):
        try:
            header = request.META.get("HTTP_HTTPSTAFFID")
            header = AllinpayStaffList.objects.get(id=header)
            return header
        except BaseException as err:
            return None

    def get_place_staff(self, p, s):
        """场所员工绑定对象"""
        try:
            r = AllinpayPlacestaffList.objects.get(pid=p.id, sid=s.id, status=1)
            s = AllinpayPlacestaffExtend.objects.get(id=r.id, mobile=1)
        except BaseException as err:
            return None
        return r

    def get_raw_header(self, header):
        parts = header.split()
        if len(parts) == 0:
            return None
        return parts[0]

    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        # 验证登录类型
        raw_header = self.get_raw_header(header)
        if raw_header is None or raw_header != "Wearer".encode():
            return None

        # # 验证场所标志
        # placer = self.get_placer(request)
        # if placer:
        #     request.placeID = placer
        # # 验证员工标志
        # staffer = self.get_staff(request)
        # if staffer:
        #     request.staffID = staffer
        # # 验证员工在职
        # PlaceStaff = self.get_place_staff(placer, staffer)
        # if PlaceStaff:
        #     request.PlaceStaff = PlaceStaff

        print("微信认证")

        validated_token = self.get_validated_token(raw_token)
        return self.get_user(validated_token), validated_token

    def get_user(self, validated_token):
        """
        Attempts to find and return a user using the given validated token.
        """
        try:
            user_id = validated_token[api_settings.USER_ID_CLAIM]
        except BaseException as err:
            raise serializers.ValidationError(["令牌不包含可识别的用户标识"])

        self.user_model = AllinpayStaffList

        try:
            user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
        except BaseException as err:
            raise serializers.ValidationError(["用户不存在"])

        print("验证员工微信")
        return user


# ======================================================================


class BarJWTAuthentication(JWTAuthentication):
    """场所端员工直连验证"""

    def get_placer(self, request):
        try:
            header = request.META.get("HTTP_HTTPPLACEID")
            header = AllinpayPlaceList.objects.get(id=header)
            return header
        except BaseException as err:
            return None

    def get_staff(self, request):
        try:
            header = request.META.get("HTTP_HTTPSTAFFID")
            header = AllinpayStaffList.objects.get(id=header)
            return header
        except BaseException as err:
            return None

    def get_place_staff(self, p, s):
        """场所员工绑定对象"""
        try:
            r = AllinpayPlacestaffList.objects.get(pid=p.id, sid=s.id, status=1)
            s = AllinpayPlacestaffExtend.objects.get(id=r.id, mobile=1)
        except BaseException as err:
            return None
        return r

    def get_raw_header(self, header):
        parts = header.split()
        if len(parts) == 0:
            return None
        return parts[0]

    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        # 验证登录类型
        raw_header = self.get_raw_header(header)
        if raw_header is None or raw_header != "Gearer".encode():
            return None

        # # 验证场所标志
        # placer = self.get_placer(request)
        # if placer:
        #     request.placeID = placer
        # # 验证员工标志
        # staffer = self.get_staff(request)
        # if staffer:
        #     request.staffID = staffer
        # # 验证员工在职
        # PlaceStaff = self.get_place_staff(placer, staffer)
        # if PlaceStaff:
        #     request.PlaceStaff = PlaceStaff

        validated_token = self.get_validated_token(raw_token)
        return self.get_user(validated_token), validated_token

    def get_user(self, validated_token):
        """
        Attempts to find and return a user using the given validated token.
        """
        try:
            user_id = validated_token[api_settings.USER_ID_CLAIM]
        except BaseException as err:
            raise serializers.ValidationError(["令牌不包含可识别的用户标识"])

        self.user_model = AllinpayStaffList

        try:
            user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
        except BaseException as err:
            raise serializers.ValidationError(["用户不存在"])

        print("验证员工场所")
        return user


class XboxJWTAuthentication(JWTAuthentication):
    """自定义身份验证- 三方场所端"""

    def get_raw_header(self, header):
        parts = header.split()
        if len(parts) == 0:
            return None
        return parts[0]

    def get_validated_token(self, token):
        try:
            r = GamePlacetokenList.objects.get(lasted=token.decode("utf-8"))
        except BaseException as err:
            return None
        else:
            return token.decode("utf-8")

    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        # 验证登录类型
        raw_header = self.get_raw_header(header)
        if raw_header is None or raw_header != "Xearer".encode():
            return None

        print("场所三方端认证")

        validated_token = self.get_validated_token(raw_token)
        return self.get_user(validated_token), validated_token

    def get_user(self, validated_token):
        self.user_model = GamePlacetokenList

        if not validated_token:
            raise serializers.ValidationError(["令牌不包含可识别的用户标识"])

        try:
            user = self.user_model.objects.get(lasted=validated_token)
        except BaseException as err:
            raise serializers.ValidationError(["用户不存在"])

        if not user.status:
            raise serializers.ValidationError(["用户已锁定"])  # 被禁用
        if user.outdate < date.today():
            raise serializers.ValidationError(["授权已过期"])  # 被禁用

        print("验证场所三方端")
        return user


class RboxJWTAuthentication(JWTAuthentication):
    """自定义身份验证- 三方后台端"""

    def get_raw_header(self, header):
        parts = header.split()
        if len(parts) == 0:
            return None
        return parts[0]

    def get_validated_token(self, token):
        try:
            r = GamoPlacetokenList.objects.get(lasted=token.decode("utf-8"))
        except BaseException as err:
            return None
        else:
            return token.decode("utf-8")

    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        # 验证登录类型
        raw_header = self.get_raw_header(header)
        if raw_header is None or raw_header != "Rearer".encode():
            return None

        print("后台三方端认证")

        validated_token = self.get_validated_token(raw_token)
        return self.get_user(validated_token), validated_token

    def get_user(self, validated_token):
        self.user_model = GamoPlacetokenList

        if not validated_token:
            raise serializers.ValidationError(["令牌不包含可识别的用户标识"])

        try:
            user = self.user_model.objects.get(lasted=validated_token)
        except BaseException as err:
            raise serializers.ValidationError(["用户不存在"])

        if not user.status:
            raise serializers.ValidationError(["用户已锁定"])  # 被禁用
        if user.outdate < date.today():
            raise serializers.ValidationError(["授权已过期"])  # 被禁用

        print("验证后台三方端")
        return user
